package com.dlc.shop.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.dlc.shop.bean.app.dto.*;
import com.dlc.shop.bean.bo.OrderChangeShopWalletAmountBO;
import com.dlc.shop.bean.bo.PlatformCommissionOrderItemBO;
import com.dlc.shop.bean.enums.*;
import com.dlc.shop.bean.event.*;
import com.dlc.shop.bean.model.*;
import com.dlc.shop.bean.param.OrderParam;
import com.dlc.shop.bean.vo.OrderAmountVO;
import com.dlc.shop.bean.vo.ShopAmountVO;
import com.dlc.shop.bean.vo.SkuStockVO;
import com.dlc.shop.bean.vo.UnDeliveryOrderExcelVO;
import com.dlc.shop.common.allinpay.constant.AllinpayConstant;
import com.dlc.shop.common.config.Constant;
import com.dlc.shop.common.constants.CacheNames;
import com.dlc.shop.common.constants.PlatformInterventionStatus;
import com.dlc.shop.common.enums.PayType;
import com.dlc.shop.common.enums.StatusEnum;
import com.dlc.shop.common.exception.YamiShopBindException;
import com.dlc.shop.common.i18n.I18nMessage;
import com.dlc.shop.common.response.ResponseEnum;
import com.dlc.shop.common.util.*;
import com.dlc.shop.dao.OrderMapper;
import com.dlc.shop.dao.OrderRefundMapper;
import com.dlc.shop.dao.PayInfoMapper;
import com.dlc.shop.manager.impl.AllinpayOrderManager;
import com.dlc.shop.manager.impl.StockManager;
import com.dlc.shop.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lgh on 2018/09/15.
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    private  final OrderMapper orderMapper;
    private  final DeliveryService deliveryService;
    private  final NotifyTemplateService notifyTemplateService;
    private  final StationService stationService;
    private  final OrderItemService orderItemService;
    private  final AllinpayOrderManager allinpayOrderManager;
    private  final OrderSettlementService orderSettlementService;
    private  final ApplicationEventPublisher eventPublisher;
    private  final OrderRefundMapper orderRefundMapper;
    private  final CategoryService categoryService;
    private  final OrderVirtualInfoService orderVirtualInfoService;
    private  final ApplicationContext applicationContext;
    private  final SkuStockLockService skuStockLockService;
    private  final PayInfoMapper payInfoMapper;
    private  final ProductService productService;
    private final ShopDetailService shopDetailService;
    private final OrderInvoiceService orderInvoiceService;
    private final StockManager stockManager;


    @Override
    public Order getOrderByOrderNumber(String orderNumber) {
        return orderMapper.getOrderByOrderNumber(orderNumber);
    }

    @Override
    public Order getOrderByOrderNumberAndUserId(String orderNumber, String userId, boolean valid) {
        Order order = orderMapper.getOrderByOrderNumberAndUserId(orderNumber, userId);
        if (valid && Objects.isNull(order)) {
            // 订单不存在
            throw new YamiShopBindException("yami.order.no.exist");
        }
        return order;
    }

    @Override
    public Order getOrderByOrderNumberAndShopId(String orderNumber, Long shopId, boolean valid) {
        Order order = orderMapper.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNumber, orderNumber).eq(Order::getShopId, shopId));
        if (valid && order == null) {
            // 订单不存在
            throw new YamiShopBindException("yami.order.no.exist");
        }
        return order;
    }


    @Override
    @CacheEvict(cacheNames = "ConfirmOrderCache", key = "#userId")
    public void removeConfirmOrderCache(String userId) {
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Order> submit(ShopCartOrderMergerDto mergerOrder) {
        String userId = mergerOrder.getUserId();
        // 扣减商品库存，本次下单使用的优惠券、积分
        TryLockStockEvent tryLockStockEvent = new TryLockStockEvent(mergerOrder, userId);
        eventPublisher.publishEvent(tryLockStockEvent);
        mergerOrder.setProdList(tryLockStockEvent.getProdList());
        List<Order> orderList = new ArrayList<>();
        // 提交订单
        eventPublisher.publishEvent(new SubmitOrderEvent(mergerOrder, orderList));
        List<OrderItem> orderItems = orderList.stream().flatMap(order -> order.getOrderItems().stream()).collect(Collectors.toList());
        // 插入订单
        saveBatch(orderList);

        // 只有普通商品才需要处理赠品
        if(Objects.equals(mergerOrder.getOrderType(),OrderType.ORDINARY)){
            // 添加赠品
            eventPublisher.publishEvent(new SubmitOrderGiveawayEvent(orderList, orderItems));
        }
        return orderList;
    }

    /**
     * 计算分摊金额
     */
    private void calculatePlatformCommission(List<Order> orders, List<OrderItem> orderItems) {
        boolean scoreOrder = Objects.equals(orders.get(0).getOrderType(), OrderType.SCORE.value());
        List<PlatformCommissionOrderItemBO> platformCommissionOrderItems = new ArrayList<>();
        for (OrderItem orderItem : orderItems) {
            PlatformCommissionOrderItemBO platformCommissionOrderItemBO = new PlatformCommissionOrderItemBO();
            platformCommissionOrderItemBO.setShopId(orderItem.getShopId());
            platformCommissionOrderItemBO.setCategoryId(orderItem.getCategoryId());
            platformCommissionOrderItemBO.setSkuId(orderItem.getSkuId());
            platformCommissionOrderItems.add(platformCommissionOrderItemBO);
        }
        // 获取整个平台的佣金比例
        List<Category> categoryRates = categoryService.listRate();
        List<PlatformCommissionOrderItemBO> data = categoryService.calculatePlatformCommission(platformCommissionOrderItems, categoryRates);
        for (OrderItem orderItem : orderItems) {
            for (PlatformCommissionOrderItemBO platformCommissionOrderItemBO : data) {
                double platformCommission = 0.0;
                // 积分订单属于平台的订单不需要计算平台佣金
                if (scoreOrder) {
                    orderItem.setPlatformCommission(platformCommission);
                    continue;
                }
                // 通过商品确定订单项
                if (Objects.equals(orderItem.getSkuId(), platformCommissionOrderItemBO.getSkuId())) {
                    // 分摊比例
                    orderItem.setRate(platformCommissionOrderItemBO.getRate());
                    // 平台佣金 = （实付金额 + 平台优惠金额） * 比例 / 100
                    platformCommission = Arith.roundByBanker(Arith.div(Arith.mul(Arith.add(orderItem.getActualTotal(), orderItem.getPlatformShareReduce()),
                            platformCommissionOrderItemBO.getRate()), 100), 2);
                    orderItem.setPlatformCommission(platformCommission);
                }
            }
        }
        Map<String, List<OrderItem>> orderNumberMap = orderItems.stream().collect(Collectors.groupingBy(OrderItem::getOrderNumber));
        for (Order order : orders) {
            double totalPlatformCommission = 0.0;
            List<OrderItem> orderItemList = orderNumberMap.get(order.getOrderNumber());
            for (OrderItem orderItem : orderItemList) {
                totalPlatformCommission = Arith.add(totalPlatformCommission, orderItem.getPlatformCommission());
            }
            order.setPlatformCommission(totalPlatformCommission);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delivery(Order order) {
        orderMapper.updateById(order);
        // 消息推送-发货提醒
        Delivery delivery = deliveryService.getById(order.getDvyId());
        String dvyName = "";
        if (delivery.getDvyName() != null) {
            dvyName = delivery.getDvyName();
        }
        notifyTemplateService.sendNotifyOfDelivery(order, dvyName, SendType.DELIVERY);
    }


    @Override
    public List<Order> listUnRefundOrderAndOrderItems(Integer orderStatus, DateTime lessThanUpdateTime) {
        return orderMapper.listUnRefundOrderAndOrderItems(orderStatus, lessThanUpdateTime);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrders(List<Order> orders) {
        if (CollectionUtil.isEmpty(orders)) {
            return;
        }
        int updateCount = orderMapper.cancelOrders(orders);
        if (Objects.equals(updateCount, 0)) {
            return;
        }
        // 更新条数不一致，获取更新成功的订单
        if (!Objects.equals(orders.size(), updateCount)) {
            Map<Long, Order> orderMap = orders.stream().collect(Collectors.toMap(Order::getOrderId, x -> x));
            List<Order> updateOrders = orderMapper.selectList(new LambdaQueryWrapper<Order>()
                    .eq(Order::getStatus, OrderStatus.CLOSE.value())
                    .in(Order::getOrderId, orderMap.keySet()));
            orders = new ArrayList<>(updateOrders.size());
            for (Order updateOrder : updateOrders) {
                orders.add(orderMap.get(updateOrder.getOrderId()));
            }
        }
        List<OrderItem> allOrderItems = new ArrayList<>();
        List<String> orderNumberList = new ArrayList<>();
        for (Order order : orders) {
            List<OrderItem> orderItems = order.getOrderItems();
            allOrderItems.addAll(orderItems);
            orderNumberList.add(order.getOrderNumber());
            eventPublisher.publishEvent(new CancelOrderEvent(order));
        }
        // 如果是秒杀订单也不必还原库存
        if (CollectionUtil.isEmpty(allOrderItems) || OrderType.SECKILL.value().equals(orders.get(0).getOrderType())) {
            return;
        }
        // 解锁库存
        skuStockLockService.unlockStock(orders);

        // 查询出微信支付并且为二维码支付的，失效掉对应支付二维码
        invalidCode(orders);

        // 更新订单发票申请状态
        if (CollUtil.isNotEmpty(orderNumberList)) {
            orderInvoiceService.update(new LambdaUpdateWrapper<OrderInvoice>()
                    .set(OrderInvoice::getInvoiceState, OrderInvoiceState.FAIL.value())
                    .in(OrderInvoice::getOrderNumber, orderNumberList));
        }

    }

    private void invalidCode(List<Order> orders) {
        Set<String> userIds = new HashSet<>();
        Set<String> orderNumbers = new HashSet<>();
        for (Order order : orders) {
            if (Objects.isNull(order.getPayType())) {
                continue;
            }
            // 如果是支付宝支付，或者微信 二维码支付直接使二维码失效
            if (Objects.equals(order.getPayType(), PayType.ALIPAY.value()) ||
                    Objects.equals(order.getPayType(), PayType.WECHATPAY_SWEEP_CODE.value())) {
                userIds.add(order.getUserId());
                orderNumbers.add(order.getOrderNumber());
            }
        }
        if (CollectionUtils.isEmpty(userIds)) {
            return;
        }
        // 如果有重复的payNo，不用失效掉二维码。
        List<PayInfo> payInfoList = payInfoMapper.listByUserIdList(userIds, DateUtil.offsetMinute(new Date(), -35));
        Iterator<PayInfo> iterator = payInfoList.iterator();
        while (iterator.hasNext()) {
            PayInfo payInfo = iterator.next();
            String[] orderNumberList = payInfo.getOrderNumbers().split(",");
            for (String orderNumber : orderNumberList) {
                if (!orderNumbers.contains(orderNumber)) {
                    iterator.remove();
                }
            }
        }
        if (CollectionUtils.isEmpty(payInfoList)) {
            return;
        }
        //失效二维码 暂时用的微信支付宝
        eventPublisher.publishEvent(new PayManagerEvent(payInfoList));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void receiptOrder(List<Order> orders) {
        if (CollectionUtils.isEmpty(orders)) {
            return;
        }
        int updateCount = orderMapper.receiptOrder(orders);
        if (Objects.equals(updateCount, 0)) {
            return;
        }
        // 更新数量不一致，获取更新成功的数据
        if (!Objects.equals(updateCount, orders.size())) {
            Map<Long, Order> orderMap = orders.stream().collect(Collectors.toMap(Order::getOrderId, x -> x));
            List<Order> updateOrders = orderMapper.selectList(new LambdaQueryWrapper<Order>()
                    .eq(Order::getStatus, OrderStatus.SUCCESS.value())
                    .in(Order::getOrderId, orderMap.keySet()));
            orders = new ArrayList<>(updateOrders.size());
            for (Order updateOrder : updateOrders) {
                orders.add(orderMap.get(updateOrder.getOrderId()));
            }
        }
        for (Order order : orders) {
            eventPublisher.publishEvent(new ReceiptOrderEvent(order));
            // 消息推送-用户已确认收货
            notifyTemplateService.sendNotifyByUserRefundDelivery(order, SendType.RECEIPT_ORDER);
        }

    }

    @Override
    public IPage<Order> pageOrdersDetailByOrderParam(Page<Order> page, OrderParam orderParam) {
        Date date = new Date();
        List<Order> orders = orderMapper.listOrdersDetailByOrderParam(new PageAdapter(page), orderParam);
        for (Order order : orders) {
            if (StrUtil.isNotBlank(order.getReceiverName()) && CharUtil.length(order.getReceiverName()) > 8) {
                order.setReceiverName(order.getReceiverName().substring(0, Math.min(8, order.getReceiverName().length() - 1)) + "...");
            }
            order.setReceiverMobile(order.getReceiverMobile() != null ? PhoneUtil.hideBetween(order.getReceiverMobile()).toString() : null);
            if (Objects.nonNull(order.getUserAddrOrder())) {
                order.getUserAddrOrder().setMobile(order.getUserAddrOrder().getMobile() != null ? PhoneUtil.hideBetween(order.getUserAddrOrder().getMobile()).toString() : order.getUserAddrOrder().getMobile());
            }
            if (Objects.equals(order.getOrderMold(), 1) && Objects.nonNull(order.getWriteOffEnd()) && DateUtil.compare(order.getWriteOffEnd(), date) < 0) {
                order.setWriteOffCodes(new ArrayList<>());
            }
            orderItemService.handleActivityOrderItem(order.getOrderItems(),null);
        }
        page.setRecords(orders);
        page.setTotal(orderMapper.countOrderDetail(orderParam));
        return page;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteOrders(List<Order> orders) {
        orderMapper.deleteOrders(orders);
    }

    @Override
    public OrderCountData getOrderCount(String userId) {
        // 获取普通订单数据
        OrderCountData countData = orderMapper.getOrderCount(userId);
        // 获取退款订单数据
        countData.setRefund(orderRefundMapper.getRefundCount(userId));
        return countData;
    }

    @Override
    public double sumTotalDistributionAmountByOrderItem(List<OrderItem> orderItems) {
        // 订单总分销金额
        double totalDistributionAmount = 0.0;
        if (CollectionUtil.isNotEmpty(orderItems)) {
            for (OrderItem orderItem : orderItems) {
                if (StrUtil.isBlank(orderItem.getDistributionCardNo())) {
                    continue;
                }
                // 如果改订单项已经退款了的话，分销员的佣金就已经回退了，不需要继续算钱
                if (Objects.equals(orderItem.getReturnMoneySts(), ReturnMoneyStsType.SUCCESS.value())) {
                    continue;
                }
                // 分销佣金
                if (orderItem.getDistributionAmount() != null && orderItem.getDistributionAmount() > 0) {
                    totalDistributionAmount = Arith.add(totalDistributionAmount, orderItem.getDistributionAmount());
                }
                // 上级分销佣金
                if (orderItem.getDistributionParentAmount() != null && orderItem.getDistributionParentAmount() > 0) {
                    totalDistributionAmount = Arith.add(totalDistributionAmount, orderItem.getDistributionParentAmount());
                }
            }
        }
        return totalDistributionAmount;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeAmount(Order order) {
        Order orderDb = orderMapper.selectOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getOrderId, order.getOrderId())
                .eq(Order::getOrderNumber, order.getOrderNumber())
        );
        if (!Objects.equals(orderDb.getStatus(), OrderStatus.UNPAY.value())) {
            // 订单状态异常，无法更改订单金额
            throw new YamiShopBindException("yami.order.unrecognized.update");
        }
        int changeAmountVersion = 0;
        if (Objects.nonNull(orderDb.getChangeAmountVersion())) {
            changeAmountVersion = orderDb.getChangeAmountVersion() + 1;
        }
        // 计算商品金额变化金额
        OrderSettlement orderSettlement = handleOrder(order, orderDb, changeAmountVersion);
        // 计算运费变化金额
        if (!Objects.equals(Arith.sub(orderDb.getFreightAmount(), orderDb.getPlatformFreeFreightAmount()), order.getFreightAmount())) {
            if (order.getFreightAmount() < 0) {
                throw new YamiShopBindException("运费金额不能小于0");
            }
            // 根据订单查看是否自营店
            // 判断会员等级是否绑定包邮权益
            if (Objects.equals(orderDb.getShopId(), Constant.MAIN_SHOP) && order.getFreightAmount() > 0) {
                eventPublisher.publishEvent(new CheckIsMainShopEvent(orderDb));
            }
            double changeFreightAmount = Arith.sub(order.getFreightAmount(), orderDb.getFreightAmount());
//            if (orderDb.getFreightAmount() == 0 && orderDb.getFreeTransfee() < 0) {
//                // 商家运费模板包邮，改价的运费由商家承担
//                orderDb.setFreeTransfee(-changeFreightAmount);
//            } else if (orderDb.getFreeTransfee() < 0) {
//                // 商家有商品运费模板包邮，改价的运费由不包邮商品承担
//                orderDb.setFreightAmount(order.getFreightAmount());
//                if (changeFreightAmount < 0) {
//                    orderDb.setFreeTransfee(Arith.add(orderDb.getFreeTransfee(), changeFreightAmount));
//                }
//                orderDb.setActualTotal(Arith.add(orderDb.getActualTotal(), changeFreightAmount));
//            } else {
//                //修改运费信息
//                orderDb.setFreightAmount(order.getFreightAmount());
//                orderDb.setActualTotal(Arith.add(orderDb.getActualTotal(), changeFreightAmount));
//            }
            //修改运费信息
            if (orderDb.getFreightAmount() == 0 && orderDb.getFreeTransfee() < 0) {
                // 商家运费模板包邮
                orderDb.setFreeTransfee(0d);
            } else if (orderDb.getFreeTransfee() < 0 && changeFreightAmount < 0) {
                // 商家有商品运费模板包邮
                orderDb.setFreeTransfee(Arith.add(orderDb.getFreeTransfee(), changeFreightAmount));
            }
            orderDb.setFreightAmount(order.getFreightAmount());
            orderDb.setActualTotal(Arith.add(orderDb.getActualTotal(), changeFreightAmount));
        }
        orderDb.setChangeAmountVersion(changeAmountVersion);
        orderMapper.updateById(orderDb);
        orderSettlement.setPayAmount(orderDb.getActualTotal());
        orderSettlementService.updateById(orderSettlement);
        // 失效对应的二维码
        invalidCode(Collections.singletonList(orderDb));
    }

    private OrderSettlement handleOrder(Order order, Order orderDb, int changeAmountVersion){
        //减少金额
        double amount = 0.00;
        //平台优惠金额
        double platformAmount = 0.00;
        Map<Long, OrderItem> collect = order.getOrderItems().stream().collect(Collectors.toMap(OrderItem::getOrderItemId, orderItem -> orderItem));
        List<OrderItem> orderItemList = orderItemService.list(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderNumber, order.getOrderNumber()));
        for (OrderItem orderItemDb : orderItemList) {
            if (Objects.equals(orderItemDb.getActivityType(),OrderActivityType.GIVEAWAY.value())){
                continue;
            }
            OrderItem orderItem = collect.get(orderItemDb.getOrderItemId());
            if (Objects.isNull(orderItem) || Objects.isNull(orderItem.getChageAmount())) {
                continue;
            }

            if (orderItem.getActualTotal() < 0.01 && orderItem.getUseScore() > 0) {
                // 如果金额小于0.01 支付积分大于0则为纯积分支付 此时不进行金额判断
                continue;
            }
            if (orderItem.getChageAmount() >= orderItemDb.getActualTotal()) {
                // 订单金额必须大于0，或者数据发生变化(请刷新后重试)
                throw new YamiShopBindException("yami.order.amount.check");
            }
            if (Objects.isNull(orderItem.getChageAmount()) || Objects.equals(orderItem.getChageAmount(), 0.00)) {
                continue;
            }
            //修改平台优惠金额
            double playformItemAmount = 0.00;
            if (orderItemDb.getPlatformShareReduce() > 0) {
                //金额减少比例 = 减少金额  % 总金额
                double proportion = Arith.div(orderItem.getChageAmount(), orderItemDb.getProductTotalAmount(), 6);
                //平台优惠金额减少金额 = 减少比例 * 原平台优惠金额
                playformItemAmount = Arith.roundByBanker(Arith.mul(proportion, orderItemDb.getPlatformShareReduce()), 2);
                //平台优惠金额 = 原平台优惠金额 - 对应比例的金额
                orderItemDb.setPlatformShareReduce(Arith.sub(orderItemDb.getPlatformShareReduce(), playformItemAmount));
            }
            // 店铺改价平台优惠减少金额
            orderItemDb.setPlatformShopChangeAmount(playformItemAmount);
            //实际金额 = 原实际金额 - 变化金额
            orderItemDb.setActualTotal(Arith.sub(orderItemDb.getActualTotal(), orderItem.getChageAmount()));
            //总优惠金额 = 变化金额 + 原总优惠金额
            orderItemDb.setShareReduce(Arith.add(orderItem.getChageAmount(), orderItemDb.getShareReduce()));
            // 店铺改价金额为订单项减少的金额
            orderItemDb.setShopChangeFreeAmount(Arith.add(orderItemDb.getShopChangeFreeAmount(), orderItem.getChageAmount()));
            orderItemDb.setChangeAmountVersion(changeAmountVersion);

            amount = Arith.add(amount, orderItem.getChageAmount());
            platformAmount = Arith.add(platformAmount, playformItemAmount);
        }
        // 重新计算佣金
        calculatePlatformCommission(Collections.singletonList(orderDb), orderItemList);
        orderItemService.updateBatchById(orderItemList);
        OrderSettlement orderSettlement = orderSettlementService.getOne(new LambdaQueryWrapper<OrderSettlement>().eq(OrderSettlement::getOrderNumber, order.getOrderNumber()));
        //修改订单信息
        orderDb.setActualTotal(Arith.sub(orderDb.getActualTotal(), amount));
        orderDb.setReduceAmount(Arith.add(orderDb.getReduceAmount(), amount));
        orderDb.setPlatformAmount(Arith.sub(orderDb.getPlatformAmount(), platformAmount));
        orderDb.setShopChangeFreeAmount(orderDb.getShopChangeFreeAmount() + amount);
        return orderSettlement;
    }

    @Override
    public List<Order> getOrderPayInfoByOrderNumber(List<String> orderNumberList) {
        return orderMapper.getOrderPayInfoByOrderNumber(orderNumberList);
    }

    @Override
    public Order getOrderDetailByOrderNumberAndShopId(String orderNumber, Long shopId) {
        Order order = orderMapper.getOrderDetailByOrderNumberAndShopId(orderNumber, shopId);
        if (Objects.isNull(order) || CollUtil.isEmpty(order.getOrderItems())){
            return order;
        }
        List<OrderRefund> orderRefundList = orderRefundMapper.getProcessingOrderRefundByOrderId(order.getOrderId());
        if (CollUtil.isEmpty(orderRefundList)){
            return order;
        }

        order.setRefundType(orderRefundList.get(0).getRefundType());

        // 整单退款
        if (Objects.equals(order.getRefundType(), RefundType.ALL.value())) {
            OrderRefund orderRefund = orderRefundList.get(0);
            for (OrderItem orderItem : order.getOrderItems()) {
                orderItem.setRefundId(orderRefund.getRefundId());
                orderItem.setReturnMoneySts(orderRefund.getReturnMoneySts());
            }
            return order;
        }
        // 单项退款
        Map<Long, OrderRefund> refundMap = orderRefundList.stream().collect(Collectors.toMap(OrderRefund::getOrderItemId, o -> o));
        for (OrderItem orderItem : order.getOrderItems()) {
            OrderRefund orderRefund = refundMap.get(orderItem.getOrderItemId());
            if (Objects.nonNull(orderRefund)) {
                orderItem.setReturnMoneySts(orderRefund.getReturnMoneySts());
                orderItem.setRefundId(orderRefund.getRefundId());
            }
        }
        return order;
    }

    @Override
    public Map<Long, Integer> getOrderItemMap(Long orderId) {
        List<OrderRefund> orderRefunds = orderRefundMapper.selectList(new LambdaQueryWrapper<OrderRefund>()
                .eq(OrderRefund::getOrderId, orderId)
                .lt(OrderRefund::getReturnMoneySts, 6)
                .gt(OrderRefund::getReturnMoneySts, 0)
        );
        // 查询申请平台介入的退款信息
        List<OrderRefund> orderRefundList = orderRefundMapper.selectList(new LambdaQueryWrapper<OrderRefund>()
                .eq(OrderRefund::getOrderId, orderId)
                .eq(OrderRefund::getPlatformInterventionStatus, PlatformInterventionStatus.APPLY.value()
        ));
        orderRefunds.addAll(orderRefundList);
        Map<Long, Integer> map = Maps.newHashMap();

        for (OrderRefund orderRefund : orderRefunds) {
            if (orderRefund.getRefundType() == 1) {
                map.put(0L, orderRefund.getReturnMoneySts());
                return map;
            }
            map.put(orderRefund.getOrderItemId(), orderRefund.getReturnMoneySts());
        }
        return map;
    }

    @Override
    public Integer countByOrderNumber(String orderNumber) {
        return orderMapper.countByOrderNumber(orderNumber);
    }

    @Override
    public UnDeliveryOrderExcelVO getOrderAndOrderItemsByOrderNumberAndShopId(String orderNumber, Long shopId) {
        return orderMapper.getOrderAndOrderItemsByOrderNumberAndShopId(orderNumber, shopId);
    }

    @Override
    public List<Order> getOrdersStatus(List<String> orderNumbers) {
        List<Order> orderList = list(new LambdaQueryWrapper<Order>()
                .select(Order::getOrderNumber,Order::getStatus,Order::getOrderType,Order::getActualTotal,Order::getUserId,Order::getShopId,Order::getCreateTime, Order::getOrderMold, Order::getDvyType).in(Order::getOrderNumber,orderNumbers));
        for (String orderNumber : orderNumbers) {
            boolean hasOrderNumber = false;
            for (Order orderStatusBO : orderList) {
                if (StrUtil.equals(orderStatusBO.getOrderNumber(), orderNumber)) {
                    hasOrderNumber = true;
                    break;
                }
            }
            if (!hasOrderNumber) {
                Order orderStatusBO = new Order();
                orderStatusBO.setOrderNumber(orderNumber);
                orderList.add(orderStatusBO);
            }
        }
        return orderList;
    }

    @Override
    public OrderAmountVO getOrdersAmountAndIfNoCancel(String userId, List<String> orderNumbers, Integer payType) {
        List<Order> ordersStatus = getOrdersStatus(orderNumbers);
        if (CollUtil.isEmpty(ordersStatus)) {
            // 订单不存在
            throw new YamiShopBindException("yami.order.no.exist");
        }
        Map<Long,ShopAmountVO> receiveMap = new HashMap<>(8);
        for (Order order : ordersStatus) {
            if (!Objects.equals(order.getUserId(), userId)) {
                throw new YamiShopBindException(ResponseEnum.UNAUTHORIZED);
            }
            if (!Objects.equals(order.getStatus(), OrderStatus.UNPAY.value())) {
                // 支付失败，订单不在未支付状态
                throw new YamiShopBindException("yami.order.pay.fail");
            }
            if (Objects.isNull(order.getStatus()) || Objects.equals(order.getStatus(), OrderStatus.CLOSE.value())) {
                // 订单已关闭
                throw new YamiShopBindException("yami.order.is.closed");
            }
            // 普通订单创建时间经过限定订单超时分钟，如果为true则早于当前时间表示过期，抛出异常
            boolean isExpired = !DateUtil.offsetMinute(order.getCreateTime(), Constant.ORDER_MAX_TIME).after(new Date());
            if(isExpired){
                // 秒杀订单已经过期，无法进行支付
                throw new YamiShopBindException("yami.order.expired");
            }
            // 如果是秒杀订单,还需判断秒杀订单有没有过期
            if(Objects.equals(order.getOrderType(),OrderType.SECKILL.value())){
                applicationContext.publishEvent(new CheckSecKillOrderEvent(order));
            }
            // 如果是团购订单,还需判断团购订单有没有过期
            if(Objects.equals(order.getOrderType(),OrderType.GROUP.value())){
                applicationContext.publishEvent(new CheckGroupOrderEvent(order));
            }
            order.setPayType(payType);
            update(order, Wrappers.lambdaUpdate(Order.class).eq(Order::getOrderNumber, order.getOrderNumber()));
            if(Objects.equals(order.getShopId(),0L)){
                continue;
            }
            if(receiveMap.containsKey(order.getShopId())){
                ShopAmountVO shopAmountVO = receiveMap.get(order.getShopId());
                shopAmountVO.setAmount(shopAmountVO.getAmount() + Arith.toLongCent(order.getActualTotal()));

            }else {
                ShopAmountVO shopAmountVO = new ShopAmountVO();
                shopAmountVO.setBizUserId(AllinpayConstant.SHOP + order.getShopId());
                shopAmountVO.setAmount(Arith.toLongCent(order.getActualTotal()));
                receiveMap.put(order.getShopId(),shopAmountVO);
            }
        }
        OrderAmountVO ordersActualAmount = orderMapper.getOrdersActualAmount(orderNumbers);
        ordersActualAmount.setReceiveList(new ArrayList<>(receiveMap.values()));
        return ordersActualAmount;
    }

    @Override
    public void updateByToPaySuccess(List<String> orderNumbers, Integer payType, Integer paySysType) {
        int updateNum = orderMapper.updateByToPaySuccess(orderNumbers, payType, paySysType);
        if (updateNum < 1) {
            throw new YamiShopBindException("yami.order.payed.repeat.operation");
        }
    }

    @Override
    public Order getOrderAndOrderItemByOrderNumber(String orderNumber) {
        return orderMapper.getOrderAndOrderItemByOrderNumber(orderNumber);
    }

    @Override
    public void getOrderItemRefundStatus(Order order) {
        if (Objects.nonNull(order.getRefundStatus()) && !Objects.equals(order.getRefundStatus(), RefundStatusEnum.DISAGREE.value())) {
            List<OrderRefund> processingOrderRefundByOrderId = orderRefundMapper.getProcessingOrderRefundByOrderId(order.getOrderId());
            for (OrderRefund orderRefund : processingOrderRefundByOrderId) {
                //整单退款
                if (orderRefund.getRefundType() == 1) {
                    for (OrderItem orderItem : order.getOrderItems()) {
                        orderItem.setReturnMoneySts(orderRefund.getReturnMoneySts());
                    }
                    break;
                }
                // 单项退款，每个单号都不一样
                for (OrderItem orderItem : order.getOrderItems()) {
                    if (Objects.equals(orderItem.getOrderItemId(), orderRefund.getOrderItemId())) {
                        orderItem.setReturnMoneySts(orderRefund.getReturnMoneySts());
                    }
                }
            }
        }
    }


    @Override
    public IPage<Order> pageByUserId(PageParam<Order> page, String userId) {
        return orderMapper.getPageByUserId(page, userId);
    }

    @Override
    public List<Order> listPendingSettlementOrders(Integer orderStatus, Date startTime) {
        return orderMapper.listPendingSettlementOrders(orderStatus, startTime);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void orderCommissionSettlement(List<Order> orders) {
        List<Long> orderIds = orders.stream().map(Order::getOrderId).collect(Collectors.toList());
        if (CollUtil.isEmpty(orderIds)) {
            return;
        }
        List<Order> list = list(new LambdaQueryWrapper<Order>()
                .in(Order::getOrderId, orderIds)
                .eq(Order::getStatus, OrderStatus.SUCCESS.value())
        );
        orderIds = list.stream().map(Order::getOrderId).collect(Collectors.toList());
        if (CollUtil.isEmpty(orderIds)) {
            return;
        }
        // 众所周知，结算之后是不能改变状态的
        int updateStats = orderMapper.settledOrder(list);
        if (updateStats == 0) {
            return;
        }
        eventPublisher.publishEvent(new OrderSettlementEvent(list));
    }


    @Override
    public IPage<MyOrderDto> orderListByStatus(PageParam<MyOrderDto> page, Integer status, Long stationId) {
        List<MyOrderDto> myOrderDtos = orderMapper.orderListByStatusAndStationId(new PageAdapter(page), status, stationId);
        for (MyOrderDto myOrderDto : myOrderDtos) {
            for (MyOrderItemDto orderItemDto : myOrderDto.getOrderItemDtos()) {
                if (Objects.equals(myOrderDto.getOrderMold(), 1)) {
                    orderItemDto.setProdCount(myOrderDto.getProductNums());
                }
            }
            orderItemService.handleActivityOrderItem(null,myOrderDto.getOrderItemDtos());
        }
        page.setRecords(myOrderDtos);
        List<MyOrderDto> orderDtoList = page.getRecords();
        for (MyOrderDto myOrderDto : orderDtoList) {
            if (StrUtil.isBlank(myOrderDto.getShopName())) {
                myOrderDto.setShopName(Constant.PLATFORM_SHOP_NAME);
            }
        }
        page.setTotal(orderMapper.countByStatusAndStationId(status, stationId));
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean orderStationByOrderNumber(List<String> orderNumberList, String userId, Long stationId) {
        if (CollUtil.isEmpty(orderNumberList)) {
            // 请选择最少一个需要自提的订单
            throw new YamiShopBindException("yami.order.need.station");
        }
        List<Order> orderList = orderMapper.getStationOrderByOrderNumbers(orderNumberList, userId, null);
        Order orderParam = new Order();
        if (CollectionUtils.isEmpty(orderList)) {
            // 订单不存在
            throw new YamiShopBindException("yami.order.no.exist");
        }
        List<String> updateOrderNumbers = new ArrayList<>(16);
        for (Order order : orderList) {
            if (Objects.isNull(order)) {
                // 订单不存在
                throw new YamiShopBindException("yami.order.no.exist");
            }
            orderParam = order;
            if (Objects.equals(order.getOrderMold(), 1)) {
                orderVirtualInfoService.orderWriteOffByOrderNumber(null, order, stationId);
                continue;
            }
            // 如果不是自提订单且不是核销订单就直接报错，如果是扫商家码进来的就不需要自提点id
            boolean notExist = !Objects.equals(order.getDvyType(), DvyType.STATION.value()) || (!Objects.equals(order.getDvyId(), stationId) && !Objects.equals(stationId, null));
            if (notExist)  {
                // 订单不存在
                throw new YamiShopBindException("yami.order.no.exist");
            }
            boolean isRefund = Objects.equals(order.getRefundStatus(), RefundStatusEnum.APPLY.value())
                    || Objects.equals(order.getRefundStatus(), RefundStatusEnum.SUCCEED.value());
            if (Objects.nonNull(order.getRefundStatus()) && isRefund) {
                // 订单退款中，无法自提
                throw new YamiShopBindException(I18nMessage.getMessage("yami.order") + order.getOrderNumber() + I18nMessage.getMessage("yami.order.station.check"));
            }
            if (!Objects.equals(order.getStatus(), OrderStatus.PADYED.value())) {
                // 订单已提货
                throw new YamiShopBindException(I18nMessage.getMessage("yami.order") + order.getOrderNumber() + I18nMessage.getMessage("yami.order.station.finish"));
            }
            order.setStatus(OrderStatus.CONSIGNMENT.value());
            order.setDvyTime(new Date());
            order.setUpdateTime(new Date());
            updateOrderNumbers.add(order.getOrderNumber());
        }

        String stationName = "";
        if (Objects.isNull(stationId)) {
            // 如果是扫商家码进来的就不需要自提点id
            stationName = shopDetailService.getById(orderList.get(0).getShopId()).getShopName();
        }else{
            Station station = stationService.getById(stationId);
            stationName = station.getStationName();
        }

//        if (!Objects.equals(station.getStatus(), StationStatusEnum.OPEN.value())) {
//            // 该自提点未在营业状态
//            throw new YamiShopBindException("yami.shop.station.not.open");
//        }


        updateBatchById(orderList);
        // 修改订单对应的商品，将状态修改全部已发货
        if (!CollectionUtils.isEmpty(updateOrderNumbers)) {
            Integer allDelivery = 0;
            orderItemService.update(new LambdaUpdateWrapper<OrderItem>()
                    .set(OrderItem::getStatus, allDelivery)
                    .in(OrderItem::getOrderNumber, updateOrderNumbers));
        }
        // 消息推送-自提点核销通知
        if (orderList.size() > 1) {
            orderParam.setOrderNumber(orderParam.getOrderNumber());
        }
        notifyTemplateService.writeOffOrder(stationName, orderList);
        return true;
    }

    @Override
    public IPage<Order> pageByUserIdAndShopId(PageParam<Order> page, String userId, Long shopId) {
        return orderMapper.getPageByUserIdAndShopId(page, userId, shopId);
    }

    @Override
    public OrderShopDto orderDetail(String orderNumber, String userId, Long stationId) {
        List<String> orderNumberList = Arrays.asList(orderNumber.split(StrUtil.COMMA));
        List<OrderShopDto> orderShopDtoList = orderMapper.orderDetailByOrderNumberList(orderNumberList,userId);
        if (CollUtil.isEmpty(orderShopDtoList)) {
            throw new YamiShopBindException("yami.order.no.exist");
        }
        OrderShopDto orderShopDto = new OrderShopDto();
        if(orderShopDtoList.size() == 1 ){
            orderShopDto = orderShopDtoList.get(0);
        } else {
            orderShopDto = orderShopDtoList.stream()
                    .filter(item ->  !Objects.equals(item.getOrderMold(), ProdMoldEnum.COMBO.value()))
                    .toList().get(0);
        }
        // 订单项
        List<OrderItem> orderItemList = orderItemService.list(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderNumber, orderShopDto.getOrderNumber()).orderByAsc(OrderItem::getOrderItemId));
        List<OrderItemDto> orderItems = BeanUtil.mapAsList(orderItemList, OrderItemDto.class);

        // 处理一下赠品和组合商品子订单项
        Map<Long, List<OrderItemDto>> giveawawMap = orderItems.stream()
                .filter(s -> Objects.equals(s.getActivityType(), OrderActivityType.GIVEAWAY.value()))
                .collect(Collectors.groupingBy(OrderItemDto::getActivityId));
        Map<Long, List<OrderItemDto>> comboMap = orderItems.stream()
                .filter(s -> Objects.equals(s.getActivityType(), OrderActivityType.COMBO_PROD.value()))
                .collect(Collectors.groupingBy(OrderItemDto::getActivityId));
        //计算订单使用积分
        Long score = 0L;
        double total = 0.0;
        Integer totalNum = 0;
        Iterator<OrderItemDto> iterator = orderItems.iterator();
        while (iterator.hasNext()) {
            OrderItemDto orderItem = iterator.next();
            if (!Objects.equals(orderItem.getPreSellStatus(), StatusEnum.ENABLE.value())){
                orderItem.setPreSellStatus(null);
            }
            if (Objects.equals(orderItem.getActivityType(), OrderActivityType.COMBO_PROD.value()) || Objects.equals(orderItem.getActivityType(), OrderActivityType.GIVEAWAY.value())) {
                iterator.remove();
                continue;
            }
            // 主订单项插入赠品订单项
            orderItem.setGiveawayList(giveawawMap.get(orderItem.getOrderItemId()));
            // 主订单项插入组合子订单项
            orderItem.setComboList(comboMap.get(orderItem.getOrderItemId()));
            score += orderItem.getUseScore();
            total = Arith.add(total, orderItem.getProductTotalAmount());
            totalNum += orderItem.getProdCount();
        }

        // 插入平台名称、订单项列表
        // 设置平台店铺名称
        if (Objects.equals(orderShopDto.getShopId(), Constant.PLATFORM_SHOP_ID)) {
            orderShopDto.setShopName(Constant.PLATFORM_SHOP_NAME);
        }

        orderShopDto.setOrderScore(score);
        orderShopDto.setTotal(total);
        orderShopDto.setTotalNum(totalNum);

        orderShopDto.setOrderItemDtos(orderItems);

        return orderShopDto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doAllinPaySettlement(OrderChangeShopWalletAmountBO orderChangeShopWalletAmountBO) {
        allinpayOrderManager.doAllinPaySettlement(orderChangeShopWalletAmountBO);
    }

    @Override
    public List<Order> listOrderAndOrderItemByOrderNumber(List<String> orderNumbers) {
        if (CollUtil.isEmpty(orderNumbers)) {
            return Collections.emptyList();
        }
        return orderMapper.listOrderAndOrderItemByOrderNumber(orderNumbers);
    }

    @Override
    public void unLockFailOrderStock() {
        while (true) {
            List<SkuStockVO> skuStockList = stockManager.unLockFailOrderStock();
            if (CollUtil.isEmpty(skuStockList)) {
                break;
            }
            int size = skuStockList.size();
            Set<String> orderNumberSet = skuStockList.stream().map(SkuStockVO::getOrderNumber).collect(Collectors.toSet());
            List<Order> dbOrderList = list(new LambdaQueryWrapper<Order>().in(Order::getOrderNumber, orderNumberSet).select(Order::getOrderNumber));
            Set<String> dbOrderNumberSet = dbOrderList.stream().map(Order::getOrderNumber).collect(Collectors.toSet());
            // 移除订单创建成功的库存锁定记录（订单创建成功的库存锁定记录，等取消订单时再处理）
            skuStockList.removeIf(skuStockLockDTO -> {
                if (dbOrderNumberSet.contains(skuStockLockDTO.getOrderNumber())) {
                    return true;
                }
                return false;
            });
            if(CollectionUtil.isEmpty(skuStockList)){
                return;
            }
            skuStockLockService.unLockStock(skuStockList);
            stockManager.trimList(CacheNames.ORDER_STOCK_LOCK, size);
        }
    }

}
